package com.fundboss.display;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import java.util.concurrent.ExecutionException;

import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.basic.BasicButtonUI;

import model.market.MarketConfig;
import model.market.MarketListener;
import model.market.ModelResults;

import org.apache.commons.math.stat.StatUtils;
import org.jfree.chart.plot.XYPlot;
import org.jgap.Configuration;
import org.jgap.impl.DefaultConfiguration;

import au.com.bytecode.opencsv.CSVReader;

//AMLOW: use showStatus?? showStatus("MyApplet: Loading image file " + file);
public class TestApplet extends JApplet{

	//AM: force eager jar loading
	static Configuration conf = new DefaultConfiguration();

	static CSVReader read;
	static{
		try{
	read = new CSVReader(null);
		}catch(Exception e){
			//suppress.. it should throw one.
		}
	}
	//////AM: end class loading.
	
	JTabbedPane tabs = new JTabbedPane();
	
	ParameterEntryPanel params;
	public void init() {
		try {
			UIManager.setLookAndFeel(
			        UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e) {
			//AM: suppress, who cares..
		} 
		
		setSize(1000, 700);
		//AMXX: SwingUtilities.invokeandwait.
		tabs.setSize(1000,700);
		add(tabs);
		params = new ParameterEntryPanel(this);
		params.setSize(900,500);
		tabs.addTab("Parameters",params);
		
		
		super.init();
	}
	
	public void kickOffMarket(MarketConfig config,TraderConfig traderConfig){
		final GraphResults results = new GraphResults();
		tabs.addTab("Results", results);
		tabs.setSelectedIndex(tabs.getTabCount()-1);
		
		JPanel tab=new JPanel();
		tab.add(new JLabel("Results"));
		JButton close = new TabButton();
		
		tab.add(close);
		close.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				int tNum =tabs.indexOfComponent(results);
				tabs.removeTabAt(tNum);
			}
		});
		tabs.setTabComponentAt(tabs.getTabCount()-1, tab);

		
		new MarketThread(config,traderConfig,results).execute();
	}
	
	private class MarketThread extends SwingWorker<ModelResults, Object> implements MarketListener{
		private MarketConfig config;
		private TraderConfig traderConfig;
		private GraphResults results;
		public MarketThread(MarketConfig config,TraderConfig traderConfig,GraphResults results){
			this.config=config;
			this.traderConfig=traderConfig;
			this.results=results;
		}

		
		protected ModelResults doInBackground() throws Exception {
//			try{
				return MarketRunner.runModel((MarketConfig)deepCopy(config),this,(TraderConfig)deepCopy(traderConfig));
//			}catch(Exception e){
//				this.error(e);
//				return null;
//			}
			
		}


		@Override
		protected void done() {
			try {
				ModelResults modelResults = get();
				if(modelResults!=null){
					results.complete(get());
				}
			} catch (Exception e) {
				results.error(e);
			}
		}
		
		@Override
		public void complete(ModelResults execute) {
			//AM: handled in done.
		}


		@Override
		public void error(Exception e) {
			publish(e);
		}
		
		@Override
		public void newIteration(int period) {
			publish(period);
		}
		
		@Override
		protected void process(List<Object> chunks) {
			for(Object chunk:chunks){
				if(chunk instanceof Exception){
					results.error((Exception)chunk);
				}else{
					//its the iteration..
					results.newIteration((Integer)chunk);
				}
			}
		}
	}
	
	
	
	static private Object deepCopy(Object oldObj) throws Exception
	   {
	      ObjectOutputStream oos = null;
	      ObjectInputStream ois = null;
	      try
	      {
	         ByteArrayOutputStream bos = 
	               new ByteArrayOutputStream(); // A
	         oos = new ObjectOutputStream(bos); // B
	         // serialize and pass the object
	         oos.writeObject(oldObj);   // C
	         oos.flush();               // D
	         ByteArrayInputStream bin = 
	               new ByteArrayInputStream(bos.toByteArray()); // E
	         ois = new ObjectInputStream(bin);                  // F
	         // return the new object
	         return ois.readObject(); // G
	      }
	      catch(Exception e)
	      {
	         System.out.println("Exception in ObjectCloner = " + e);
	         throw(e);
	      }
	      finally
	      {
	         oos.close();
	         ois.close();
	      }
	   }
	   


	
	private class TabButton extends JButton  {
        public TabButton() {
            int size = 17;
            setPreferredSize(new Dimension(size, size));
            setToolTipText("close this tab");
            //Make the button looks the same for all Laf's
            setUI(new BasicButtonUI());
            //Make it transparent
            setContentAreaFilled(false);
            //No need to be focusable
            setFocusable(false);
            setBorder(BorderFactory.createEtchedBorder());
            setBorderPainted(false);
            //Making nice rollover effect
            //we use the same listener for all buttons
            addMouseListener(buttonMouseListener);
            setRolloverEnabled(true);
            //Close the proper tab by clicking the button
            
        }

        

        //we don't want to update UI for this button
        public void updateUI() {
        }

        //paint the cross
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g.create();
            //shift the image for pressed buttons
            if (getModel().isPressed()) {
                g2.translate(1, 1);
            }
            g2.setStroke(new BasicStroke(2));
            g2.setColor(Color.BLACK);
            if (getModel().isRollover()) {
                g2.setColor(Color.MAGENTA);
            }
            int delta = 6;
            g2.drawLine(delta, delta, getWidth() - delta - 1, getHeight() - delta - 1);
            g2.drawLine(getWidth() - delta - 1, delta, delta, getHeight() - delta - 1);
            g2.dispose();
        }
    }

    private final static MouseListener buttonMouseListener = new MouseAdapter() {
        public void mouseEntered(MouseEvent e) {
            Component component = e.getComponent();
            if (component instanceof AbstractButton) {
                AbstractButton button = (AbstractButton) component;
                button.setBorderPainted(true);
            }
        }

        public void mouseExited(MouseEvent e) {
            Component component = e.getComponent();
            if (component instanceof AbstractButton) {
                AbstractButton button = (AbstractButton) component;
                button.setBorderPainted(false);
            }
        }
    };

}
